/*
 * PCL.cpp
 *
 *  Created on: 2012. 10. 15.
 *      Author: dalxx
 */

#include <Arduino.h>
#include "PLC.h"
#include "PLCLib/RelayContainer.h"
#include "PLCLib/ParseTool.h"
#include "EEPROMStream.h"




const char* PLC::CMD_PLC_SET="PLC_SET";
const char* PLC::CMD_STOP="PLC_STOP";
const char* PLC::CMD_START="PLC_START";
const char* PLC::CMD_CHANG_MOD="PLC_CHANGE_MOD";
const char* PLC::CMD_STATUS="PLC_STATUS";
const char* PLC::CMD_EEPROM_CLEAR="PLC_CLEAR";
const char* PLC::CMD_EEPROM_READ="PLC_EE_READ";
const char* PLC::CMD_EEPROM_WRITE_STATUS="PLC_EE_WRITE_ST";

const char* PLC::EEPROM_KEWORD="PLC";
const char* PLC::OUT_OK="OK";
const char* PLC::ERR_FMT_PLC_SET="PLC_SET_READ_ERROR";

const char* VREF_DEFAULT="DEFAULT";
const char* VREF_INTERNAL="INTERNAL";
const char* VREF_EXTERNAL="EXTERNAL";



PLC::PLC(Stream& _cmdReader) {


	this->cmdConsole=&_cmdReader;

	this->container.setBuffer(this->full_buffer, BUFFER_SIZE);


}

PLC::~PLC() {

}



void PLC::doPLC() {
	this->processCommand();

	this->container.update();
}


void PLC::processCommand() {
	if(Serial.available())
	{
		int size=this->cmdConsole->readBytesUntil('\n', this->full_buffer, BUFFER_SIZE);
		this->full_buffer[size]='\0';
#ifdef  SERIAL_TRACE_ON
		Serial.println(this->full_buffer);

#endif

		if(strcmp(full_buffer,PLC::CMD_PLC_SET)==0)
		{
			{
				EEPRomStream stream(NULL, EEPROM_SIZE);
				//EEPRomStream data_stream((char*)EEPROM_HEADERSIZE, EEPROM_SIZE-EEPROM_HEADERSIZE);
				stream.Stream::write(PLC::EEPROM_KEWORD);
				stream.Stream::write("\n");
				stream.Stream::write((unsigned char*)&BUILD_NUMBER,sizeof(int));
				stream.flush();

				int i,c, pos;
				pos=stream.getPosition();
				stream.seek(EEPROM_HEADERSIZE);
				for(i=0;i<EEPROM_SIZE;i++)
				{
					c=PLCLib::ParseTool::timedRead(*this->cmdConsole);
					//c=this->cmdConsole->read();
	//#ifdef  SERIAL_TRACE_ON
	//				Serial.print(i);
	//				Serial.print(" : ");
	//				Serial.println((char)c);
	//				Serial.println(pos);
	//#endif
					if(c==-1) break;
					stream.write(c);

				}
				stream.flush();

				this->eePlcVariables[0].start=(char*)EEPROM_HEADERSIZE;
				this->eePlcVariables[0].size=i;
				this->eePlcVariables[1].start=this->eePlcVariables[0].start+this->eePlcVariables[0].size;
				stream.seek(pos);
				stream.Stream::write((unsigned char*)this->eePlcVariables,sizeof(EEPROM_Variable)*EEPROM_VARIABLE_NUMBER);
				stream.flush();
	//#ifdef  SERIAL_TRACE_ON
	//			stream.seek(0);
	//				for(int i=0;i<10;i++)
	//				{
	//					Serial.println(stream.read());
	//				}
	//
	//#endif
	//#ifdef  SERIAL_TRACE_ON
	//
	//		Serial.print("Header :");
	//		Serial.print((int)this->eePlcVariables[1].start);
	////		Serial.print(" Header size :");
	////		Serial.print(this->eePlcVariables[0].size);
	//		Serial.print(" [1].size :");
	//		Serial.println(this->eePlcVariables[1].size);
	//		stream.resetBuffer(this->eePlcVariables[0].start,this->eePlcVariables[0].size);
	//
	//
	//		while((c=stream.read()) !=-1)
	//		{
	//			Serial.write(c);
	//		}
	//
	//#endif
				this->initFromEEPROM(true);
				stream.seek(pos);
				stream.Stream::write((unsigned char*)this->eePlcVariables,sizeof(EEPROM_Variable)*EEPROM_VARIABLE_NUMBER);
				stream.flush();
			}
			this->writeStatusToEEPROM();

		}
		else if(strcmp(full_buffer,PLC::CMD_STATUS)==0)
		{
			PLCLib::Relay* rel;
			int nRelay;
			rel=this->container.getRelayList(nRelay);
			this->cmdConsole->println("relay_number:value");
			for(int i=0;i<nRelay;i++)
			{
				this->cmdConsole->print(rel[i].number);
				this->cmdConsole->print(":");
				this->cmdConsole->println((int)rel[i].status);

			}

		}
		else if(strcmp(full_buffer,PLC::CMD_EEPROM_CLEAR)==0)
		{
			EEPRomStream header_stream(NULL, EEPROM_SIZE);
			for (int i = 0; i < 512; i++)
				header_stream.write(0);
		}
		else if(strcmp(full_buffer,PLC::CMD_EEPROM_READ)==0)
		{
			this->initFromEEPROM(false);
		}
		else if(strcmp(full_buffer,PLC::CMD_EEPROM_WRITE_STATUS)==0)
		{
			this->writeStatusToEEPROM();
		}


	}
}

void PLC::initFromEEPROM(bool isCmdSet) {
	int len, build_num;
	EEPRomStream stream(NULL, EEPROM_SIZE);
	len=stream.readBytesUntil('\n',this->full_buffer, BUFFER_SIZE);
	this->full_buffer[len]='\0';
//#ifdef  SERIAL_TRACE_ON
//		Serial.println(PLC::EEPROM_KEWORD);
//		Serial.println(this->full_buffer);
//#endif
	if(strcmp(PLC::EEPROM_KEWORD, this->full_buffer)!=0)
		return ;
//#ifdef  SERIAL_TRACE_ON
//		Serial.println("init#2");
//#endif
	stream.readBytes((char*)&build_num,sizeof(int));
	if(build_num!=BUILD_NUMBER)
		return ;

	stream.readBytes((char*)this->eePlcVariables,sizeof(EEPROM_Variable)*EEPROM_VARIABLE_NUMBER);
	stream.resetBuffer(this->eePlcVariables[0].start, this->eePlcVariables[0].size);
	this->container.init(stream);
	stream.resetBuffer(this->eePlcVariables[1].start, this->eePlcVariables[1].size);
	int nRelay;
	PLCLib::Relay* rel;
	rel=this->container.getRelayList(nRelay);
	this->eePlcVariables[1].size=nRelay*sizeof(PLCLib::Relay);
	if(!isCmdSet)
	{
		stream.resetBuffer(this->eePlcVariables[1].start, this->eePlcVariables[1].size);
		stream.readBytes((char*)rel,this->eePlcVariables[1].size);
	}




}

void PLC::writeStatusToEEPROM() {
	int nRelay;
	PLCLib::Relay* rel;
	rel=this->container.getRelayList(nRelay);
#ifdef  SERIAL_TRACE_ON
		Serial.print(" [1]:");
		Serial.print((int)this->eePlcVariables[1].start);
		Serial.print(" [1]size:");
		Serial.println(this->eePlcVariables[1].size);
#endif
	EEPRomStream stream(this->eePlcVariables[1].start, this->eePlcVariables[1].size);
	stream.Stream::write((unsigned char*)rel,this->eePlcVariables[1].size);
	stream.flush();

}
